Participação virtual (refazer um contest encerrado) — MOJ docs

Participação virtual (refazer um contest encerrado)

A participação virtual deixa uma conta do Treino Livre refazer um contest que já terminou. A prova roda no tempo de quem participa. Os times oficiais aparecem como "fantasmas": cada um resolve cada problema no mesmo minuto em que resolveu na prova real. No fim, a linha do participante fica gravada no placar virtual do contest, marcada como virtual.

Página: /treino/virtual/?c=<contest> (site principal). Código: server/api/v1/lib/virtual.sh, handlers/treino/virtual/*, web/treino/virtual/, web/shared/virtual-board.js.

1. De onde veio o desenho

Plataforma O que faz O que o MOJ copiou O que o MOJ mudou
Codeforces Botão em toda prova encerrada. Regras de honra. Horário de início. Placar no tempo relativo. Uma participação por prova. Cancela só antes de qualquer ação. Linha marcada com #. Regras de honra, horário de início, placar no tempo relativo, uma vez por conta, linha marcada. Desistência explícita (ver §4): virtual abandonado não polui o placar.
AtCoder A aba "Virtual Standings" anda no tempo virtual, mas a aba "Standings" mostra o resultado final. Um placar só, sempre no tempo do participante.

2. Quando um contest oferece participação virtual

O dono liga o módulo virtual (Central › Módulos). O portão vr_load confere todas as condições a cada requisição:

  1. módulo virtual ligado;
  2. contest não é secreto (SECRET);
  3. modo ICPC (versão 1);
  4. início e fim definidos;
  5. prova encerrada para todas as sedes (contest_over_for_all: fim + maior prorrogação);
  6. placar final descongelado (FREEZE_TIME = 0 — o "Encerrar evento" faz isso);
  7. todos os problemas são públicos no treino (contests/treino/var/jsons/<id>.json com public != false).

Participação virtual de problema privado não existe. Nada do virtual lê jsons-private/ nem MOJ_PROBLEMS_DIR. O enunciado vem da rota pública /treino/problem?id=.

Blindagem

3. Como a run funciona

Arquivo Conteúdo
contests/treino/users/<login>/virtual/<cid>.json estado da run (autoritativo; acompanha o rename)
contests/treino/users/<login>/virtual/<cid>.subs subids etiquetados
contests/<cid>/virtual/runs/<login>.json snapshot gravado ao finalizar (imune a rejulgamento)
contests/<cid>/var/virtual-feed.json(.gz) feed dos fantasmas (cache)
contests/<cid>/var/virtual-board.json agregado dos snapshots (cache)

4. Desistir × gravar (decisão de 2026-09-18)

Situação Resultado
Rodando, ≤ 15 min de prova ou nenhum Accepted botão Desistir: nada é gravado e a tentativa volta
Rodando, > 15 min e ≥ 1 Accepted não dá mais para desistir; o resultado será gravado
Tempo acabou com 0 Accepted descartada sozinha; conta como desistência
Encerrar agora com 0 Accepted vira desistência
Já desistiu 2 vezes a próxima largada é definitiva: sem desistir, grava mesmo com 0

As submissões de uma run descartada continuam no histórico do treino. Constantes: VR_GRACE_S (900), VR_MAX_DISCARDS (2), VR_SCHEDULE_MAX_S (7 d), VR_PENDING_MAX_S (1 h: pendente mais velho que isso não segura a finalização).

5. O placar

6. Painel do dono e moderação

Evento › Virtual: mostra o portão aberto em partes (o que falta), o link da página e as participações gravadas. remove/restore tiram ou devolvem uma linha (auditado). Rota: /contest/admin/virtual.

Devolver a tentativa (reset): para um testador, ou para quem teve problema. A ação apaga a linha gravada e põe de lado o estado da conta naquele contest (as desistências também). A conta pode largar de novo. A regra "uma vez por conta" continua para todos os outros. As submissões ficam no histórico do treino. A ação é auditada (virtual-reset).

7. Fora da versão 1

Times virtuais; placar OBI/heurístico; rodadas arquivadas; moj-comp --virtual; ver ao vivo outras participações virtuais em andamento.